# -*- coding: utf-8 -*-

import cv2 as cv
import numpy as np

img = cv.imread("photos/dog.jpg")
cv.imshow("dog", img)

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("Gray", gray)

#######################
#方法一
canny = cv.Canny(gray, 125, 175)
cv.imshow("Canny", canny)

# blur = cv.GaussianBlur(gray, (5,5), cv.BORDER_DEFAULT)
# cv.imshow("Blur", blur)
# canny = cv.Canny(blur, 125, 175)
# cv.imshow("Canny", canny)

# image 单通道图像矩阵，可以是灰度图，但更常用的是二值图像，
#       一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像
#
# mode 轮廓的检索模式，有四种
# cv2.RETR_EXTERNAL     表示只检测外轮廓
# cv2.RETR_LIST         检测的轮廓放在list
# cv2.RETR_TREE         建立一个内外层轮廓的tree
#
# method 轮廓的近似办法
# CV_CHAIN_APPROX_NONE：保存物体边界上所有连续的轮廓点到contours向量内
# CV_CHAIN_APPROX_SIMPLE：仅保存轮廓的拐点信息，把所有轮廓拐点处的点保存入contours向量内，
#                         拐点与拐点之间直线段上的信息点不予保留
#
# contours 返回一个list，list中每个元素都是图像中的一个轮廓
# hierarchy 返回轮廓的关系，每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3]，
#           分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号
# contours, hierarchies = cv.findContours(canny, mode=cv.RETR_LIST, method=cv.CHAIN_APPROX_SIMPLE)
# print(f'{len(contours)} contours found')

# blank = np.zeros(img.shape, dtype="uint8")

# # image为三通道才能显示轮廓
# cv.drawContours(blank, contours, contourIdx=-1, color=(0,0,255), thickness=1)
# cv.imshow("Contours Drawn", blank)

#######################
#方法二

# image 单通道图像，通常来说为灰度图
# thresh 阈值
# maxval 当像素值超过了阈值（或者小于阈值，根据type来决定），所赋予的值
# type 二值化操作的类型，包含以下5种类型： 
# cv2.THRESH_BINARY 超过阈值部分取maxval，小于阈值部分取0
# cv2.THRESH_BINARY_INV 大于阈值部分取0，小于阈值部分取maxval
# cv2.THRESH_TRUNC 截断操作，大于阈值部分取maxval，小于阈值部分不变
# cv2.THRESH_TOZERO 化零操作，大于阈值部分不变，小于阈值部分取0
# cv2.THRESH_TOZERO_INV 反向化零操作,大于阈值部分取0，小于阈值部分不变
#
# ret 设置的阈值，数值等于thresh
ret, thresh = cv.threshold(gray, thresh=125, maxval=255, type=cv.THRESH_BINARY)
cv.imshow("Thresh", thresh)

contours, hierarchies = cv.findContours(thresh, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
print(f'{len(contours)} contours found')

cv.waitKey(0)